﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace Net
{
    class PackageParser
    {
        ObjectState objectState;
        byte packageIdentifier;

        public PackageParser(ObjectState objectState)
        {
            this.objectState = objectState;
            packageIdentifier = objectState.buffer[4];
        }

        public void ProcessPackage()
        {
            string code = Encoding.ASCII.GetString(objectState.buffer, objectState.offset + 5, 4);
            switch (code)
            {
                case "1001":      //登录成功
                case "1002":      //用户名或密码错误
                case "1003":      //连续密码错误三次，三分钟内禁止此帐号再登录
                    PostLoginResult();
                    break;
                case "1004":      //被迫下线
                case "1005":      //服务器关机维护的通知
                case "1006":      //与服务器的连接中断
                    ProcessOutLine();
                    break;
                case "1011":       //修改密码成功
                case "1012":       //修改密码失败
                case "1013":       //旧密码不正确
                    PostChangePasswordResult();
                    break;
                case "1021":      //客户端为最新版本，无需更新
                    ProcessNeedUpdateResult(false);
                    break;
                case "1022":      //客户端需要更新
                    ProcessNeedUpdateResult(true);
                    break;
                case "1031":      //无可更新文件
                case "1032":      //可更新的文件列表及大小
                    ProcessUpdateFileInfo();
                    break;
                case "1033":      //接收更新文件数据
                    ReceiveUpdateFileData();
                    break;
                case "1034":      //更新完成
                    UpdateComplete();
                    break;
                case "1041":      //接收请求的DataSet
                case "1051":    //接收请求的DataTable
                    DBDataReach();
                    break;
                case "1061":    //接收SQL语句影响的行数
                    IntReach();
                    break;
                default:
                    new ProcedureResultParser(objectState).ParseProcedurePackage();
                    break;
            }
        }

        private void PostLoginResult()
        {
            NetCallback netCallback = NetService.callbackMap[packageIdentifier];
            netCallback.AsyncObject = Encoding.Unicode.GetString(objectState.buffer, objectState.offset + 9, objectState.packageLength - 9);
            netCallback.Execute();
        }

        private void ProcessOutLine()
        {
            String str = Encoding.Unicode.GetString(objectState.buffer, objectState.offset + 9, objectState.packageLength - 9);
            new NetService().ProcessOutLine(str);
        }

        private void PostChangePasswordResult()
        {
            NetCallback netCallback = NetService.callbackMap[packageIdentifier];
            netCallback.AsyncObject = Encoding.Unicode.GetString(objectState.buffer, objectState.offset + 9, objectState.packageLength - 9);
            netCallback.Execute();
        }

        private void ProcessNeedUpdateResult(bool needUpdate)
        {
            NetCallback netCallback = NetService.callbackMap[packageIdentifier];
            netCallback.AsyncObject = needUpdate;
            netCallback.Execute();
        }

        private void ProcessUpdateFileInfo()
        {
            NetCallback netCallback = NetService.callbackMap[packageIdentifier];
            string result = Encoding.Unicode.GetString(objectState.buffer, objectState.offset + 9, objectState.packageLength - 9);
            string[] s = result.Split('|');
            int updateFileNumber = s.Length / 2;
            string[] fileName = new string[updateFileNumber];
            int[] fileLength = new int[updateFileNumber];
            for (int i = 0; i < updateFileNumber; i++)
            {
                fileName[i] = s[i * 2];
                fileLength[i] = Convert.ToInt32(s[i * 2 + 1]);
            }
            UpdateInfo updateInfo = new UpdateInfo();
            updateInfo.updateFileName = fileName;
            updateInfo.updateFileLength = fileLength;
            netCallback.AsyncObject = updateInfo;
            netCallback.Execute();
        }

        private void ReceiveUpdateFileData()
        {
            NetCallback netCallback = NetService.callbackMap[packageIdentifier];
            UpdateInfo updateInfo = (UpdateInfo)netCallback.AsyncObject;
            int index = BitConverter.ToInt32(objectState.buffer, objectState.offset + 9);

            string destinationPath = Directory.GetCurrentDirectory() + "\\UpdateTemp";
            if (!Directory.Exists(@destinationPath))
            {
                Directory.CreateDirectory(destinationPath);
            }
            string path = destinationPath + "\\" + updateInfo.updateFileName[index];
            FileStream fs;
            if (index != updateInfo.updateIndex)
            {
                fs = new FileStream(path, FileMode.Create, FileAccess.Write);
                ((UpdateInfo)netCallback.AsyncObject).updateIndex = index;
            }
            else
            {
                fs = new FileStream(path, FileMode.Append, FileAccess.Write);
            }
            BinaryWriter binarywrite = new BinaryWriter(fs);
            binarywrite.Write(objectState.buffer, 13, objectState.packageLength - 13);
            binarywrite.Close();
            fs.Close();
            ((UpdateInfo)netCallback.AsyncObject).dataLength = objectState.packageLength - 13;
            netCallback.Execute();
        }

        private void UpdateComplete()
        {
            NetCallback netCallback = NetService.callbackMap[packageIdentifier];
            UpdateInfo updateInfo = ((UpdateInfo)netCallback.AsyncObject);
            updateInfo.updateIndex = updateInfo.updateFileName.Length;
            updateInfo.dataLength = BitConverter.ToInt32(objectState.buffer, objectState.offset + 9);
            netCallback.Execute();
        }

        private void DBDataReach()
        {
            NetCallback netCallback = NetService.callbackMap[packageIdentifier];
            netCallback.AsyncObject = ByteArrayParser.ByteArrayToObject(objectState.buffer, objectState.offset + 9, objectState.packageLength - 9);
            netCallback.Execute();
        }

        private void IntReach()
        {
            NetCallback netCallback = NetService.callbackMap[packageIdentifier];
            netCallback.AsyncObject = BitConverter.ToInt32(objectState.buffer, objectState.offset + 9);
            netCallback.Execute();
        }
    }
}
